package de.mauandmau;

import java.util.HashMap;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.FPSCounter;
import org.anddev.andengine.entity.IUpdateHandler;
import org.anddev.andengine.entity.Scene;
import org.anddev.andengine.entity.handler.runnable.RunnableHandler;
import org.anddev.andengine.input.touch.IOnAreaTouchListener;
import org.anddev.andengine.input.touch.IOnSceneTouchListener;
import org.anddev.andengine.input.touch.ITouchArea;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;
import org.anddev.andengine.ui.activity.BaseGameActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import de.mauandmau.adt.Card;
import de.mauandmau.entity.CardSprite;
import de.mauandmau.util.constants.Constants;

/**
 * @author Nicolas Gramlich
 * @since 18:20:40 - 18.06.2010
 */
public class GameActivity extends BaseGameActivity {
	// ===========================================================
	// Constants
	// ===========================================================

	private static final int CAMERA_WIDTH = 720;
	private static final int CAMERA_HEIGHT = 480;

	// ===========================================================
	// Fields
	// ===========================================================

	private Camera mCamera;
	private Texture mCardDeckTexture;

	protected CardSprite mSelectedCardSprite;

	private HashMap<Card, TextureRegion> mCardTotextureRegionMap;
	private RunnableHandler mRemoveRunnableHandler;
	private Server server;
	private Client client;
	private IUpdateHandler mRunnableRemoveHandler;

	// ===========================================================
	// Constructors
	// ===========================================================

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	@Override
	protected void onCreate(Bundle pSavedInstanceState) {
		super.onCreate(pSavedInstanceState);
		ActivityRegistry.register(this);
		server = new Server();
		new Thread(server).start();
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		client = new Client(this) {
			@Override
			protected void handleMessage(String string) {
				Log.w(Utils.TAG, "from server: " + string);
				if (string.equals("Kill")) {
					GameActivity.this.mRemoveRunnableHandler
							.addRunnable(new Runnable() {
								@Override
								public void run() {
									GameActivity.this.mEngine.getScene()
											.getTopLayer().clear();
								}
							});
				} else {
					addCard(GameActivity.this.mEngine.getScene(),
							Card.values()[Integer.parseInt(string)]);
				}

			}
		};
		new Thread(client).start();
	}

	/* Creates the menu items */
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0, 0, 0, "Austeilen");
		menu.add(0, 1, 0, "Beenden");
		return true;
	}

	/* Handles item selections */
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case 0:
			server.sendRandomCardToAllClients();
			return true;
		case 1:
			ActivityRegistry.finishAll();
			return true;
		}
		return false;
	}

	@Override
	protected void onDestroy() {
		server.destroy();
		client.destroy();
		super.onDestroy();
	}

	@Override
	public Engine onLoadEngine() {
		this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE,
				new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),
				this.mCamera, false));
	}

	@Override
	public void onLoadResources() {
		this.mCardDeckTexture = new Texture(1024, 512);

		TextureRegionFactory.createFromAsset(this.mCardDeckTexture, this,
				"gfx/carddeck.png", 0, 0);

		this.mCardTotextureRegionMap = new HashMap<Card, TextureRegion>();

		for (final Card card : Card.values()) {
			final TextureRegion cardTextureRegion = TextureRegionFactory
					.extractFromTexture(this.mCardDeckTexture, card
							.getTexturePositionX(), card.getTexturePositionY(),
							Constants.CARD_WIDTH, Constants.CARD_HEIGHT);
			this.mCardTotextureRegionMap.put(card, cardTextureRegion);
		}

		this.getEngine().getTextureManager().loadTexture(this.mCardDeckTexture);
	}

	@Override
	public Scene onLoadScene() {
		this.getEngine().registerPreFrameHandler(new FPSCounter());
		final Scene scene = new Scene(1);
		// this.mRemoveRunnableHandler = new RunnableHandler();
		// this.getEngine().registerPostFrameHandler(this.mRunnableRemoveHandler);

		scene.setBackgroundColor(0.09804f, 0.6274f, 0.8784f);

		scene.setOnSceneTouchListener(new IOnSceneTouchListener() {
			@Override
			public boolean onSceneTouchEvent(final Scene pScene,
					final MotionEvent pSceneMotionEvent) {
				return updateSelectedCardPosition(pSceneMotionEvent);
			}
		});

		scene.setOnAreaTouchListener(new IOnAreaTouchListener() {
			@Override
			public boolean onAreaTouched(final ITouchArea pTouchArea,
					final MotionEvent pSceneMotionEvent) {
				if (pSceneMotionEvent.getAction() == MotionEvent.ACTION_DOWN) {
					GameActivity.this.mSelectedCardSprite = (CardSprite) pTouchArea;
					GameActivity.this.mSelectedCardSprite.setScale(1.2f);
					return true;
				} else {
					return updateSelectedCardPosition(pSceneMotionEvent);
				}
			}
		});

		return scene;
	}

	public void removeCardSprite(final CardSprite pCardSprite) {
		this.mRemoveRunnableHandler.addRunnable(new Runnable() {
			@Override
			public void run() {
				final Scene scene = GameActivity.this.mEngine.getScene();
				scene.unregisterTouchArea(pCardSprite);
				scene.getTopLayer().removeEntity(pCardSprite);
			}
		});
	}

	@Override
	public void onLoadComplete() {

	}

	// ===========================================================
	// Methods
	// ===========================================================

	private boolean updateSelectedCardPosition(
			final MotionEvent pSceneMotionEvent) {
		if (GameActivity.this.mSelectedCardSprite != null) {
			if (pSceneMotionEvent.getAction() == MotionEvent.ACTION_MOVE) {
				GameActivity.this.mSelectedCardSprite.setPosition(
						pSceneMotionEvent.getX() - Constants.CARD_WIDTH / 2,
						pSceneMotionEvent.getY() - Constants.CARD_HEIGHT / 2);
			} else if (pSceneMotionEvent.getAction() == MotionEvent.ACTION_UP) {
				GameActivity.this.mSelectedCardSprite.setScale(1.0f);
				GameActivity.this.mSelectedCardSprite = null;
			}
			return true;
		} else {
			return false;
		}
	}

	public void addCard(final Scene pScene, final Card pCard) {
		final CardSprite cardSprite = new CardSprite((float) Math.random()
				* CAMERA_WIDTH, (float) Math.random() * CAMERA_HEIGHT,
				this.mCardTotextureRegionMap.get(pCard));

		pScene.getTopLayer().addEntity(cardSprite);
		pScene.registerTouchArea(cardSprite);
	}

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================
}
